using System.IO;
using System.Security.Cryptography;

namespace Service
{
	internal class CryptoHelper
	{
		private const ulong FcTag = 18158797384510146255uL;
		private const int BufferSize = 131072;
		private static RandomNumberGenerator rand = new RNGCryptoServiceProvider();
		private static bool CheckByteArrays(byte[] b1, byte[] b2)
		{
			bool result;
			if (b1.Length == b2.Length)
			{
				for (int i = 0; i < b1.Length; i++)
				{
					if (b1[i] != b2[i])
					{
						result = false;
						return result;
					}
				}
				result = true;
			}
			else
			{
				result = false;
			}
			return result;
		}
		private static SymmetricAlgorithm CreateRijndael(string password, byte[] salt)
		{
			PasswordDeriveBytes passwordDeriveBytes = new PasswordDeriveBytes(password, salt, "SHA256", 1000);
			SymmetricAlgorithm symmetricAlgorithm = Rijndael.Create();
			symmetricAlgorithm.KeySize = 256;
			symmetricAlgorithm.Key = passwordDeriveBytes.GetBytes(32);
			symmetricAlgorithm.Padding = PaddingMode.PKCS7;
			return symmetricAlgorithm;
		}
		private static byte[] GenerateRandomBytes(int count)
		{
			byte[] array = new byte[count];
			CryptoHelper.rand.GetBytes(array);
			return array;
		}
		public static void EncryptFile(string inFile, string outFile, string password, CryptoProgressCallBack callback)
		{
			using (FileStream fileStream = File.OpenRead(inFile))
			{
				using (FileStream fileStream2 = File.OpenWrite(outFile))
				{
					long length = fileStream.Length;
					int max = (int)length;
					byte[] array = new byte[131072];
					int num = 0;
					byte[] array2 = CryptoHelper.GenerateRandomBytes(16);
					byte[] array3 = CryptoHelper.GenerateRandomBytes(16);
					SymmetricAlgorithm symmetricAlgorithm = CryptoHelper.CreateRijndael(password, array3);
					symmetricAlgorithm.IV = array2;
					fileStream2.Write(array2, 0, array2.Length);
					fileStream2.Write(array3, 0, array3.Length);
					HashAlgorithm hashAlgorithm = SHA256.Create();
					using (CryptoStream cryptoStream = new CryptoStream(fileStream2, symmetricAlgorithm.CreateEncryptor(), CryptoStreamMode.Write))
					{
						using (CryptoStream cryptoStream2 = new CryptoStream(Stream.Null, hashAlgorithm, CryptoStreamMode.Write))
						{
							BinaryWriter binaryWriter = new BinaryWriter(cryptoStream);
							binaryWriter.Write(length);
							binaryWriter.Write(18158797384510146255uL);
							int num2;
							while ((num2 = fileStream.Read(array, 0, array.Length)) != 0)
							{
								cryptoStream.Write(array, 0, num2);
								cryptoStream2.Write(array, 0, num2);
								num += num2;
								callback(0, max, num);
							}
							cryptoStream2.Flush();
							cryptoStream2.Close();
							byte[] hash = hashAlgorithm.Hash;
							cryptoStream.Write(hash, 0, hash.Length);
							cryptoStream.Flush();
							cryptoStream.Close();
						}
					}
				}
			}
		}
		public static void DecryptFile(string inFile, string outFile, string password, CryptoProgressCallBack callback)
		{
			using (FileStream fileStream = File.OpenRead(inFile))
			{
				using (FileStream fileStream2 = File.OpenWrite(outFile))
				{
					int max = (int)fileStream.Length;
					byte[] array = new byte[131072];
					int num = 0;
					byte[] array2 = new byte[16];
					fileStream.Read(array2, 0, 16);
					byte[] array3 = new byte[16];
					fileStream.Read(array3, 0, 16);
					SymmetricAlgorithm symmetricAlgorithm = CryptoHelper.CreateRijndael(password, array3);
					symmetricAlgorithm.IV = array2;
					int num2 = 32;
					long num3 = -1L;
					HashAlgorithm hashAlgorithm = SHA256.Create();
					using (CryptoStream cryptoStream = new CryptoStream(fileStream, symmetricAlgorithm.CreateDecryptor(), CryptoStreamMode.Read))
					{
						using (CryptoStream cryptoStream2 = new CryptoStream(Stream.Null, hashAlgorithm, CryptoStreamMode.Write))
						{
							BinaryReader binaryReader = new BinaryReader(cryptoStream);
							num3 = binaryReader.ReadInt64();
							ulong num4 = binaryReader.ReadUInt64();
							if (18158797384510146255uL != num4)
							{
								throw new CryptoHelpException("File Corrupted!");
							}
							long num5 = num3 / 131072L;
							long num6 = num3 % 131072L;
							int num7 = 0;
							int num8;
							while ((long)num7 < num5)
							{
								num8 = cryptoStream.Read(array, 0, array.Length);
								fileStream2.Write(array, 0, num8);
								cryptoStream2.Write(array, 0, num8);
								num2 += num8;
								num += num8;
								callback(0, max, num2);
								num7++;
							}
							if (num6 > 0L)
							{
								num8 = cryptoStream.Read(array, 0, (int)num6);
								fileStream2.Write(array, 0, num8);
								cryptoStream2.Write(array, 0, num8);
								num2 += num8;
								num += num8;
								callback(0, max, num2);
							}
							cryptoStream2.Flush();
							cryptoStream2.Close();
							fileStream2.Flush();
							fileStream2.Close();
							byte[] hash = hashAlgorithm.Hash;
							byte[] array4 = new byte[hashAlgorithm.HashSize / 8];
							num8 = cryptoStream.Read(array4, 0, array4.Length);
							if (array4.Length != num8 || !CryptoHelper.CheckByteArrays(array4, hash))
							{
								throw new CryptoHelpException("File Corrupted!");
							}
						}
					}
					if ((long)num != num3)
					{
						throw new CryptoHelpException("File Sizes don't match!");
					}
				}
			}
		}
	}
}
